package com.quickfile.gaefilesystem;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.quickfile.File;
import com.quickfile.FileFilter;
import com.quickfile.FilenameFilter;

public class FileImpl extends File {

	private String filepath;

	// 从数据库中查询
	private Entity getEntityByQuery() {
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		// 查询是否存在此路径的实体
		Query query = new Query("GaeFile");
		query.addFilter("path", FilterOperator.EQUAL, filepath);
		Entity gaeFile = ds.prepare(query).asSingleEntity();
		return gaeFile;
	}

	public FileImpl(String filepath) {
		this.filepath = filepath;
	}

	@Override
	public boolean canRead() {
		return true;
	}

	@Override
	public boolean canWrite() {
		return true;
	}

	@Override
	public int compareTo(File pathname) {
		return filepath.compareTo(pathname.getPath());
	}

	@Override
	public boolean createNewFile() throws IOException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public File createTempFile2(String prefix, String suffix)
			throws IOException {
		throw new RuntimeException("尚未实现此功能！");
	}

	@Override
	public File createTempFile2(String prefix, String suffix, File directory)
			throws IOException {
		throw new RuntimeException("尚未实现此功能！");
	}

	@Override
	public boolean delete() {
		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		Entity entity = this.getEntityByQuery();
		if (entity == null)
			return true;
		ds.delete(entity.getKey());
		return true;
	}

	@Override
	public void deleteOnExit() {
		delete();
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == null)
			return false;
		return obj.equals(this);
	}

	@Override
	public boolean exists() {
		return getEntityByQuery() != null;
	}

	@Override
	public File getAbsoluteFile() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getAbsolutePath() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public File getCanonicalFile() throws IOException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getCanonicalPath() throws IOException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getName() {
		return (String) getEntityByQuery().getProperty("name");
	}

	@Override
	public String getParent() {
		return (String) getEntityByQuery().getProperty("parent");
	}

	@Override
	public File getParentFile() {
		return new FileImpl(getParent());
	}

	@Override
	public String getPath() {
		return (String) getEntityByQuery().getProperty("path");
	}

	@Override
	public int hashCode() {
		return filepath.hashCode();
	}

	@Override
	public boolean isAbsolute() {
		return true;
	}

	@Override
	public boolean isDirectory() {
		return !isFile();
	}

	@Override
	public boolean isFile() {
		return (Boolean) getEntityByQuery().getProperty("isFile");
	}

	@Override
	public boolean isHidden() {
		return false;
	}

	@Override
	public long lastModified() {
		return (Long) getEntityByQuery().getProperty("lastModified");
	}

	@Override
	public long length() {
		return (Long) getEntityByQuery().getProperty("length");
	}

	@Override
	public String[] list() {
		return list(null);
	}

	@Override
	public String[] list(FilenameFilter filter) {

		DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
		Query query = new Query("GaeFile");
		query.addFilter("parent", FilterOperator.EQUAL, this.getPath());
		List<Entity> subEntityList = ds.prepare(query).asList(
				FetchOptions.Builder.withDefaults());
		List<String> rtnList = new ArrayList<String>();

		for (Entity subEntity : subEntityList) {
			String subEntityFilePath = (String) subEntity.getProperty("path");
			if (filter != null && !filter.accept(this, subEntityFilePath))
				continue;
			rtnList.add(subEntityFilePath);
		}
		return rtnList.toArray(new String[0]);
	}

	@Override
	public File[] listFiles() {
		String[] filePathArray = list();
		List<File> fileList = new ArrayList<File>();
		for (String filePath : filePathArray) {
			fileList.add(new FileImpl(filePath));
		}
		return fileList.toArray(new File[0]);
	}

	@Override
	public File[] listFiles(FileFilter filter) {
		String[] filePathArray = list();
		List<File> fileList = new ArrayList<File>();
		for (String filePath : filePathArray) {
			if (filter != null && !filter.accept(new FileImpl(filePath)))
				continue;
			fileList.add(new FileImpl(filePath));
		}
		return fileList.toArray(new File[0]);
	}

	@Override
	public File[] listFiles(FilenameFilter filter) {
		String[] filePathArray = list();
		List<File> fileList = new ArrayList<File>();
		for (String filePath : filePathArray) {
			if (filter != null && !filter.accept(this, filePath))
				continue;
			fileList.add(new FileImpl(filePath));
		}
		return fileList.toArray(new File[0]);
	}

	@Override
	public File[] listRoots2() {
		File[] fileArray = new File[1];
		fileArray[0] = new FileImpl("/");
		return fileArray;
	}

	@Override
	public boolean mkdir() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean mkdirs() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean renameTo(File dest) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean setLastModified(long time) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean setReadOnly() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public URI toURI() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public URL toURL() throws MalformedURLException {
		// TODO Auto-generated method stub
		return null;
	}

}
